package 
{
	import away3d.cameras.Camera3D;
	import away3d.containers.ObjectContainer3D;
	import away3d.containers.Scene3D;
	import away3d.containers.View3D;
	import away3d.controllers.HoverController;
	import away3d.entities.Mesh;
	import away3d.entities.Sprite3D;
	import away3d.lights.PointLight;
	import away3d.materials.ColorMaterial;
	import away3d.materials.lightpickers.StaticLightPicker;
	import away3d.materials.methods.EnvMapMethod;
	import away3d.materials.TextureMaterial;
	import away3d.primitives.SkyBox;
	import away3d.primitives.SphereGeometry;
	import away3d.textures.BitmapCubeTexture;
	import away3d.textures.BitmapTexture;
	import away3d.textures.Texture2DBase;
	import away3d.utils.Cast;
	import com.darcey.debug.DebugBox;
	import com.darcey.ui.SliderList;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.ui.Keyboard;
	import flash.utils.getTimer;
	
	/**
	 * ...
	 * @author 
	 */
	public class Main extends Sprite 
	{
		// Imagenes
		
		[Embed(source = "../embedded_assets/sun.png")]
		private var SunImg:Class;
		
		[Embed(source = "../embedded_assets/sunEffect.png")]
		private var SunEffectImg:Class;
		
		[Embed(source = "../embedded_assets/mercury.jpg")]
		private var MercuryImg:Class;
		
		[Embed(source = "../embedded_assets/venus.jpg")]
		private var VenusImg:Class;
		
		[Embed(source = "../embedded_assets/earth.jpg")]
		private var EarthImg:Class;
		
		[Embed(source = "../embedded_assets/mars.jpg")]
		private var MarsImg:Class;
		
		[Embed(source = "../embedded_assets/jupiter.jpg")]
		private var JupiterImg:Class;
		
		[Embed(source = "../embedded_assets/saturn.jpg")]
		private var SaturnImg:Class;
		
		[Embed(source = "../embedded_assets/uranus.png")]
		private var UranusImg:Class;
		
		[Embed(source = "../embedded_assets/neptune.jpg")]
		private var NeptuneImg:Class;
		
		[Embed(source = "../embedded_assets/moon.jpg")]
		private var MoonImg:Class;
		
		
		
		// Fondo
		[Embed(source = "../embedded_assets/fondo.png")]
		private var SkyImg:Class;
		
		// Engine
		private var view:View3D;
		private var scene:Scene3D;
		private var camera:Camera3D;
		
		// Control de la camara
		private var controller:HoverController;
		
		private var move:Boolean = false;
		private var lastPanAngle:Number;
		private var lastTiltAngle:Number;
		private var lastMouseX:Number;
		private var lastMouseY:Number;
		
		// Luz
		private var light:PointLight;
		private var lightPicker:StaticLightPicker;
		
		// Materiales & texturas
		private var sunEffectMat:TextureMaterial;
		
		// Fondo
		private var skyTex:BitmapCubeTexture;
		private var sky:SkyBox;
		
		// Objetos
		private var _sun : Star;
		private var _planets : Vector.<Star>;
		
		// Contenedor para trabajar objetos en grupo
		private var container:ObjectContainer3D;
		
		// UI
		private var _current:int = 0;
		
		private var _sliders : SliderList;
		
		private var _time : Number = 1;
		
		private var lastMeanAnomaly: Number = 0;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
			
			initEngine();
			initLights();
			initMaterials();
			initModels();
			initUI();
			initListeners();
		}
		
		private function initEngine():void
		{
			
			scene = new Scene3D();
			
			camera = new Camera3D();
			camera.lens.far = 10000000;
			
			view = new View3D();
			view.scene = scene;
			view.camera = camera;
			view.antiAlias = 2;
			
			controller = new HoverController(camera, null, 180, 0, 2000);
			
			addChild(view);			
		}
		
		private function initLights():void
		{
			light = new PointLight();
			light.specular = 0;
			light.color = 0xfffac4;
			
			scene.addChild(light);
			
			lightPicker = new StaticLightPicker([light]);
		}
		
		private function initMaterials():void
		{
			// Fondo
			skyTex = new BitmapCubeTexture(
				Cast.bitmapData(SkyImg), Cast.bitmapData(SkyImg),
				Cast.bitmapData(SkyImg), Cast.bitmapData(SkyImg),
				Cast.bitmapData(SkyImg), Cast.bitmapData(SkyImg)
			);
			
			sunEffectMat = new TextureMaterial(Cast.bitmapTexture(SunEffectImg));
			sunEffectMat.alphaBlending = true;
			
		}
		
		private function initModels():void
		{
			// Fondo
			sky = new SkyBox(skyTex);
			scene.addChild(sky);
		
			// Sol
			var sunEffect:Sprite3D = new Sprite3D(sunEffectMat, 2048, 2048);			
			scene.addChild(sunEffect);
			
			_sun = new SphericalStar(256, SunImg);
			scene.addChild(_sun);
			
			// Planetas
			_planets = new Vector.<Star>();
			_planets.push(
				new SphericalStar(49, MercuryImg, lightPicker, new Orbit(0.241, 0.206, 0.387), 0, 3000),
				new SphericalStar(120, VenusImg, lightPicker, new Orbit(0.615, 0.007, 0.723), 0, 3000),
				new SphericalStar(128, EarthImg, lightPicker, new Orbit(1.0, 0.017, 1.0), 0, 3000),
				new SphericalStar(68, MarsImg, lightPicker, new Orbit(1.880, 0.093, 1.523), 3, 3000),
				new SphericalStar(1435, JupiterImg, lightPicker, new Orbit(11.867, 0.048, 5.203), 3, 3000),
				new SphericalStar(1203, SaturnImg, lightPicker, new Orbit(29.461, 0.056, 9.539), 3, 3000),
				new SphericalStar(521, UranusImg, lightPicker, new Orbit(84.030, 0.046, 19.185), 3, 3000),
				new SphericalStar(502, NeptuneImg, lightPicker, new Orbit(164.815, 0.010, 30.061), 3, 3000));
			
			for each(var planet : Star in _planets)
			{
				_sun.addChild(planet);
				scene.addChild(planet.getOrbitSegmentSet(60, 0.5));
			}
			
			// Lunas
				
		}
		
		private function initUI() : void
		{			
			_sliders = new SliderList();
			_sliders.x = 5;
			_sliders.y = 15;
			_sliders.addObjectSlider("Velocidad", 200, 0, 100, 1, this, "time");
			_sliders.addObjectSlider("Zoom", 200, 800, 100000, 2000, controller, "distance");
			addChild(_sliders);
		}
		
		private function initListeners() : void
		{
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
			// Tamaño
			stage.addEventListener(Event.RESIZE, onResize);
			
			// Arrastrar para girar la cámara
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, false, 1);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			// Rueda del mouse para el zoom
			stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
			// Teclado flechas
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			
			
			
			onResize();
		}
		
		
		
		//-----------------------------------------------------------------
		// EVENTOS
		//-----------------------------------------------------------------
		
		private function onMouseDown(e:MouseEvent):void
		{
			lastPanAngle = controller.panAngle;
			lastTiltAngle = controller.tiltAngle;
			lastMouseX = stage.mouseX;
			lastMouseY = stage.mouseY;
			move = true;
			
			stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave);
		}
		
		private function onMouseUp(e:MouseEvent):void
		{
			move = false;
			stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave);
		}
		
		private function onMouseWheel(e:MouseEvent):void
		{
			if ( controller.distance > 1000 || e.delta < 0 ) {
				controller.distance -= e.delta * 100;
			}
			//stage.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
		}
		
		private function onMouseLeave(e:Event):void
		{
			move = false;
			stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave);
		}
		
		private function onKeyDown(e:KeyboardEvent):void
		{
			switch(e.keyCode)
			{
				case Keyboard.RIGHT:
					if (_current < _planets.length-1) 
					{
						controller.lookAtObject = _planets[++_current];
					}
					break;
				case Keyboard.LEFT:
					if (_current > 0)
					{
						controller.lookAtObject = _planets[--_current];
					}
			}
		}
		
		
		private function onEnterFrame(e:Event):void
		{
			
			if (move) {
				controller.panAngle = 0.3 * (stage.mouseX - lastMouseX) + lastPanAngle;
				controller.tiltAngle = 0.3 * (stage.mouseY - lastMouseY) + lastTiltAngle;
			}
			
			for each(var planet : Star in _planets)
			{
				planet.setPosition(getTimer() * _time * 0.00001);
			}
			
			view.render();
		}
		
		private function onResize(e:Event = null):void
		{
			view.width = stage.stageWidth;
			view.height = stage.stageHeight;
		}

		
		//-----------------------------------------------------------------
		// VARIABLES UI
		//-----------------------------------------------------------------
		public function get time() : Number
		{
			return _time;
		}
		public function set time(value : Number) : void
		{
			_time = value;
		}
	}
	
}